<template>
  <div>
    <el-popover
      ref="popover"
      placement="bottom-start"
      trigger="click"
      class="tree__select"
      @show="onShowPopover"
      @hide="onHidePopover"
    >
      <div class="tree_wrap">
        <el-tree
          ref="tree"
          class="select-tree"
          highlight-current
          :data="data"
          :props="props"
          @node-click="onClickNode"
        >
          <span
            class="custom-tree-node"
            slot-scope="{ node }"
          >
          {{ node.label }}
        </span>
        </el-tree>
      </div>
      <el-input
        slot="reference"
        ref="input"
        :maxlength="0"
        :minlength="0"
        v-model="labelModel"
        :class="{ 'rotate': showStatus }"
        suffix-icon="el-icon-arrow-down"
        :placeholder="placeholder"
      ></el-input>
    </el-popover>
  </div>
</template>

<script>
export default {
  name: "TreeSelect",
  props: {
    // 接收绑定参数
    value: [String, Number],
    // 选项数据
    options: {
      type: Array,
      required: true
    },
    // 输入框占位符
    placeholder: {
      type: String,
      required: false,
      default: "请选择"
    },
    // 树节点配置选项
    props: {
      type: Object,
      required: false,
      default: () => ({
        parent: "parentId",
        value: "id",
        label: "name",
        children: "children"
      })
    },
    children: [Number, String, Boolean]
  },
  // 设置绑定参数
  model: {
    prop: "value",
    event: "selected"
  },
  computed: {
    // 是否为树状结构数据
    dataType() {
      const jsonStr = JSON.stringify(this.options);
      return jsonStr.indexOf(this.props.children) !== -1;
    },
    // 若非树状结构，则转化为树状结构数据
    data() {
      return this.dataType ? this.options : this.switchTree();
    },
    // 输入框显示值
    labelModel: {
      get() {
        return this.value ? this.queryTree(this.data, this.value) : "";
      },
      set(val) {
        if (!val) {
          this.valueModel = "";
        }
      }
    }
  },
  data() {
    return {
      // 树状菜单显示状态
      showStatus: false,
      // 实际请求传值
      valueModel: "0"
    };
  },
  created() {
    this.labelModel = this.value ? this.queryTree(this.data, this.value) : "";
  },
  methods: {
    // 单击节点
    onClickNode(node) {
      if (node.children && node.children.length) return false;
      this.labelModel = node[this.props.label];
      this.valueModel = node[this.props.value];
      this.onCloseTree();
    },
    // 偏平数组转化为树状层级结构
    switchTree() {
      return this.cleanChildren(this.buildTree(this.options, "0"));
    },
    // 隐藏树状菜单
    onCloseTree() {
      this.$refs.popover.showPopper = false;
    },
    // 显示时触发
    onShowPopover() {
      this.showStatus = true;
    },
    // 隐藏时触发
    onHidePopover() {
      this.showStatus = false;
      this.$emit("selected", this.valueModel);
    },
    // 搜索树状数据中的 ID
    queryTree(tree, id) {
      let stark = [];
      stark = stark.concat(tree);
      while (stark.length) {
        const temp = stark.shift();
        if (temp[this.props.children]) {
          stark = stark.concat(temp[this.props.children]);
        }
        if (temp[this.props.value] === id) {
          return temp[this.props.label];
        }
      }
      return "";
    },
    // 将一维的扁平数组转换为多层级对象
    buildTree(data, id = "0") {
      const fa = parentId => {
        const temp = [];
        for (let i = 0; i < data.length; i++) {
          const n = data[i];
          if (n[this.props.parent] === parentId) {
            n.children = fa(n.rowGuid);
            temp.push(n);
          }
        }
        return temp;
      };
      return fa(id);
    },
    // 清除空 children项
    cleanChildren(data) {
      const fa = list => {
        list.map(e => {
          if (e.children.length) {
            fa(e.children);
          } else {
            delete e.children;
          }
          return e;
        });
        return list;
      };
      return fa(data);
    }
  }
};
</script>

<style lang="scss" scoped>
@import "@/styles/mixin.scss";
.el-input.el-input--suffix {
  cursor: pointer;
  overflow: hidden;
}
.el-input.el-input--suffix.rotate .el-input__suffix {
  transform: rotate(180deg);
}
.tree_wrap {
  max-width: 400px;
  max-height: 350px;
  min-height: 200px;
  overflow: auto;
  @include scrollBar;
  .custom-tree-node {
    font.active {
      color: #c0c4cc;
      cursor: no-drop;
    }
  }
}
</style>
<style>
.tree_wrap .el-scrollbar .el-scrollbar__wrap {
  overflow-x: hidden;
}
.tree_wrap .el-tree > .el-tree-node {
  min-width: 100%;
  display: inline-block;
}
</style>
